package away3d.cameras.lenses ;


import away3d.core.math.Matrix3DUtils ;
import flash.geom.Matrix3D ;
import flash.geom.Vector3D ;



/**
 * The PerspectiveLens object provides a projection matrix that projects 3D geometry with perspective distortion.
 */
class PerspectiveLens extends LensBase
{
    
    
    private var _fieldOfView    : Float ;
    private var _focalLengthInv : Float ;
    private var _yMax           : Float ;
    private var _xMax           : Float ;
    
    
    
    /**
     * Creates a new PerspectiveLens object.
     * @param fieldOfView The vertical field of view of the projection.
     */
    public function new( ?fieldOfView_ : Float = 60 )
    {
        
        super() ;
        fieldOfView = fieldOfView_ ;
        
    }
    
    
    public var fieldOfView( get_fieldOfView, set_fieldOfView ) : Float ;
    
    
    /**
     * The vertical field of view of the projection.
     */
    private function get_fieldOfView() : Float
    {
        
        return _fieldOfView ;
        
    }
    
    
    private function set_fieldOfView( value : Float )
    {
        
        if( value == _fieldOfView ) return ;
        _fieldOfView = value ;
        // tan( fov/2 )
        _focalLengthInv = Math.tan( _fieldOfView*Math.PI/360 ) ;
        invalidateMatrix() ;
        
    }
    
    
    /**
     * @inheritDoc
     */
    override private  function updateMatrix()
    {
        
        var raw = Matrix3DUtils.RAW_DATA_CONTAINER ;
        
        _yMax = _near*_focalLengthInv ;
        _xMax = _yMax*_aspectRatio ;
        
        // assume symmetric frustum
        raw[ 0  ] = _near/_xMax ;
        raw[ 5  ] = _near/_yMax ;
        raw[ 10 ] = _far/( _far-_near ) ;
        raw[ 11 ] = 1 ;
        raw[ 1  ] = raw[ 2  ] = raw[ 3  ] = raw[ 4 ] =
        raw[ 6  ] = raw[ 7  ] = raw[ 8  ] = raw[ 9 ] =
        raw[ 12 ] = raw[ 13 ] = raw[ 15 ] = 0 ;
        raw[ 14 ] = -_near*raw[ 10 ] ;
        
        _matrix.copyRawDataFrom( raw ) ;
        
        var yMaxFar = _far*_focalLengthInv ;
        var xMaxFar = yMaxFar*_aspectRatio ;
        
        _frustumCorners[ 0  ] = _frustumCorners[ 9  ] = -_xMax ;
        _frustumCorners[ 3  ] = _frustumCorners[ 6  ] = _xMax ;
        _frustumCorners[ 1  ] = _frustumCorners[ 4  ] = -_yMax ;
        _frustumCorners[ 7  ] = _frustumCorners[ 10 ] = _yMax ;
        
        _frustumCorners[ 12 ] = _frustumCorners[ 21 ] = -xMaxFar ;
        _frustumCorners[ 15 ] = _frustumCorners[ 18 ] = xMaxFar ;
        _frustumCorners[ 13 ] = _frustumCorners[ 16 ] = -yMaxFar ;
        _frustumCorners[ 19 ] = _frustumCorners[ 22 ] = yMaxFar ;
        
        _frustumCorners[ 2  ] = _frustumCorners[ 5  ] = _frustumCorners[ 8  ] = _frustumCorners[ 11 ] = _near ;
        _frustumCorners[ 14 ] = _frustumCorners[ 17 ] = _frustumCorners[ 20 ] = _frustumCorners[ 23 ] = _far ;
        
    }
    
    
}